作用域是原始碼中定義變數的區域,他規範了目前程式碼應該要去哪裡查找變數,而作用域又可分為 靜態作用域 與 動態作用域,首先先來了解兩者的差別。

靜態作用域又稱作語法作用域(Lexical scoping),他在函數定義時就已經決定作用域,而且不會再改變,JavaScript 屬於此類。
以下為靜態作用域範例,運作步驟如下:
變數 num 賦予值 1。函式 fn2,在函式內命名一個 變數 num 賦予值 2,因靜態作用域的關係,函式 fn2 中的 變數 num,作用域只在 函式 fn2 中,接著呼叫 函式 fn1。函式 fn1 內因沒有 變數 num,又因靜態作用域的關係,所以會向外層(全域)查找,故 console.log(num); 顯示為 1。// 靜態作用域範例
var num = 1;
function fn1() {
console.log(num); // 1
// 因靜態作用域,又因 fn1 沒有變數 num,所以會向外(全域)查找
}
function fn2() {
var num = 2;
//變數 num 作用域只在函式 fn2 中
fn1();
}
fn2();
動態作用域會在函式調用時才會決定作用域。
以下為動態作用域範例,運作步驟如下:
變數 num 賦予值 1。函式 fn2,在函式內命名一個 變數 num 賦予值 2,接著呼叫 函式 fn1。函式 fn1 內因沒有 變數 num,又因動態作用域的關係 - 函式調用時才會決定作用域,所以會向上一層 函式 fn2 查找 變數 num,故 console.log(num); 顯示為 2。// 動態作用域範例
var num = 1;
function fn1() {
console.log(num); // 2
// 因動態作用域,在函式調用時才會決定作用域,所以會向上一層 fn2 宣告的位置找變數的值
}
function fn2() {
var num = 2;
fn1();
}
fn2();
若所有作用域都找不到變數時,則會出現 ReferenceError: 變數 is not defined 的錯誤訊息,範例如下。
